#include <string.h>
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
 
#define DEV_FILE     "/dev/i2c-1"
 
#define SHT2X_ADDR             0x40
#define SHT2X_SOFTRESET        0xFE
#define SHT2X_MEAS_TEMPER      0xF3
#define SHT2X_MEAS_HUMIDITY    0xF5
 
void msleep(unsigned int time);
int sht2x_init(void);
int sht2x_softreset(int fd);
int sht2x_send_cmd_wr(int fd, char *which);
int sht2x_get_temper_rh(int fd, float *temper, float *rh);
 
int main(int argc, char **argv)
{
	int         fd = -1;
	int         ret = -1;
	float       temper;   
	float       rh;       //humidity
	
	fd = sht2x_init();
	if( fd < 0 )
	{
		printf("sht2x_init failure.\n");
		return -1;
	}
	ret = sht2x_softreset(fd);
	if( ret < 0 )
	{
		printf("sht2x_softreset failure.\n");
		return -2;
	}
	// while(1){
	// 	ret = sht2x_get_temper_rh(fd, &temper, &rh);
	// 	if( ret < 0 )
	// 	{
	// 		printf("sht2x_get_temper_rh failure.\n");
	// 		return -3;
	// 	}
	// 	printf("Temperature = %fC  Relative humidity = %f\n", temper, rh);

	// 	msleep(1000);
	// }
	ret = sht2x_get_temper_rh(fd, &temper, &rh);
	if( ret < 0 )
	{
		printf("sht2x_get_temper_rh failure.\n");
		return -3;
	}
	printf("Temperature = %fC  Relative humidity = %f\n", temper, rh);

	close(fd);
	return 0;
}
 
void msleep(unsigned int time)
{
	struct timespec sleeper, temp;
	sleeper.tv_sec = (time_t)(time/1000);
	sleeper.tv_nsec = (long)(time%1000)*1000000;
	nanosleep(&sleeper, &temp);
	return ; 
}
 
int sht2x_init(void)
{
	int    fd = -1;
	fd = open(DEV_FILE, O_RDWR);
	if( fd < 0 )
	{
		printf("i2c device open failure: %s\n", strerror(errno));
		return -1;
	}
	ioctl(fd, I2C_TENBIT, 0);
	ioctl(fd, I2C_SLAVE, SHT2X_ADDR);
	return fd;
}
 
int sht2x_softreset(int fd)
{
	int            ret = -1;
    uint8_t        buf[2] = {0};
 
	if( fd < 0 )
	{
		printf("input the invalid argument.\n");
		return -1;
	}	
	
    buf[0] = SHT2X_SOFTRESET;
	ret = write(fd, buf, 1);
	if( ret < 0 )
	{
		printf("write softrest cmd to sht2x failure.\n");
		return -2;
	}
	msleep(50);
		
	return 0;
}
 
int sht2x_send_cmd_wr(int fd, char *which)
{
	int              ret = -1;
	uint8_t          buf[2] = {0};
 
	if( fd < 0 )
	{
		printf("input the invalid argument.\n");
		return -1;
	}
	
	if( strcmp(which, "temper") == 0 )
	{
        buf[0] = SHT2X_MEAS_TEMPER;
        ret = write(fd, buf, 1);
		if( ret < 0 )
		{
			printf("write temper cmd to sht2x failure.\n");
			return -2;
		}
		msleep(85);  //datasheet typ=66, max=85
	}
	else if( strcmp(which, "rh") == 0 )
	{
        buf[0] = SHT2X_MEAS_HUMIDITY;
        ret = write(fd, buf, 1);
		if( ret < 0 )
		{
			printf("write humidity cmd to sht2x failure.\n");
			return -3;
		}
		msleep(29);  //datasheet typ=22, max=29
	}
	return 0;
}
 
int sht2x_get_temper_rh(int fd, float *temper, float *rh)
{
	uint8_t              buf[4] = {0};
	int                  ret = -1;
 
	if( fd<0 || !temper || !rh )
	{
		printf("input the invalid arguments.\n");
		return -1;
	}
	ret = sht2x_send_cmd_wr(fd, "temper");
	if( ret < 0 )
	{
		printf("sht2x_send_cmd_wr temper failure.\n");
		return -2;
	}
	else
	{
        ret = read(fd, buf, 3);
		if( ret < 0 )
		{
			printf("get the temper failure.\n");
			return -3;
		}
		*temper = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;
	}
 
	ret = sht2x_send_cmd_wr(fd, "rh");
	if( ret < 0 )
	{
		printf("sht2x_send_cmd_wr rh failure.\n");
		return -2;
	}
	else
	{
        read(fd, buf, 3);
		if( ret < 0 )
		{
			printf("get the temper failure.\n");
			return -3;
		}
		*rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;
	}
	return 0;
}